# Django imports
from django.http import HttpResponse

# Project imports
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.views.decorators.csrf import csrf_exempt
from .models import Contact, Phone, Address

# Standard imports
from json import dumps
from datetime import date


def address_book(request):
    """
    Fetches contacts, phones and addresses then returns as JSON.

    JSON response structure:
    {
        contact_id: [
            name,
            surname,
            avatar,
            birthday,
            [[phone_id, phone_type, phone]],
            [[address_id, country, city, street, apartment, flat, type]]
        ],
    }

    Response is rendered to address_book.html.
    """

    # Fetching data from db
    ## Contacts ##
    contacts = Contact.objects.all().values_list(
        'id', 'name', 'surname', 'avatar', 'birthday'
    ).order_by('id')
    ## Phones ##
    phones = Phone.objects.all().values_list(
        'id', 'contact_id', 'type', 'value'
    ).order_by('contact')
    ## Addresses ##
    addresses = Address.objects.all().values_list(
        'id',
        'contact_id',
        'country',
        'city',
        'street',
        'apartment',
        'flat',
        'type'
    ).order_by('contact')

    # Converting data to dicts to speed up lookups during merge
    contacts_dict = {
        contact[0]: list(contact[1:]) + [[], []] for contact in contacts
    }
    # No need to store allocated contacts queryset, so releasing it
    del contacts

    # Merging phones
    for phone in phones:
        contacts_dict[phone[1]][4].append([phone[0], phone[2], phone[3]])

    # Merging phones
    for address in addresses:
        contacts_dict[address[1]][5].append(
            [
                address[0],
                address[2],
                address[3],
                address[4],
                address[5],
                address[6],
                address[7]
            ]
        )

    # Python JSON module does not know how to handle Datetime and Date
    # Implementing handler for python Date objects
    date_handler = (
        lambda obj: obj.isoformat()
        if isinstance(obj, date)
        else None
    )
    data = dumps(obj=contacts_dict, default=date_handler)
    return render_to_response(
        'address_book.html',
        {'data': data},
        context_instance=RequestContext(request)
    )


@csrf_exempt
def create_contact(request):
    new_contact = Contact()
    new_contact.name = request.POST['profile_name']
    new_contact.surname = request.POST['profile_surname']
    new_contact.birthday = request.POST['profile_date']
    new_contact.save()

    if 'profile_mobile_phone' in request.POST:
        new_phone = Phone()
        new_phone.contact = new_contact
        new_phone.type = Phone.PHONE_TYPE_MOBILE
        new_phone.value = request.POST['profile_mobile_phone']
        new_phone.save()

    if 'profile_home_phone' in request.POST:
        new_phone = Phone()
        new_phone.contact = new_contact
        new_phone.type = Phone.PHONE_TYPE_HOME
        new_phone.value = request.POST['profile_home_phone']
        new_phone.save()

    if 'profile_work_phone' in request.POST:
        new_phone = Phone()
        new_phone.contact = new_contact
        new_phone.type = Phone.PHONE_TYPE_OFFICE
        new_phone.value = request.POST['profile_work_phone']
        new_phone.save()

    if 'profile_country' in request.POST \
        or 'profile_city' in request.POST \
        or 'profile_apartment' in request.POST:
        new_address = Address()
        new_address.contact = new_contact
        new_address.country = request.POST.get('profile_country', None)
        new_address.city = request.POST.get('profile_city', None)
        new_address.apartment = request.POST.get('profile_apartment', None)
        new_address.type = Address.ADDRESS_TYPE_NONE
        new_address.save()

    response_data = {}
    response_data['is_success'] = True
    response_data['profile_id'] = new_contact.id

    return HttpResponse(dumps(response_data), content_type="application/json")


@csrf_exempt
def delete_contact(request):
    return {}